package com.clei.netty.file.dto;

import com.clei.netty.file.enums.FileCmdTypeEnum;
import com.clei.utils.ByteUtil;
import com.clei.utils.helper.BytesReader;

/**
 * file client server之间数据传输的消息体
 *
 * @author Y
 * @date 2022-04-21
 */
public class MsgBody {

    /**
     * 序号
     * 从1开始
     */
    private int seq;

    /**
     * 回应
     * 对应序号 从1开始 0表示无对应请求
     */
    private int ack;

    /**
     * 命令类型
     *
     * @see FileCmdTypeEnum
     */
    private byte cmd;

    /**
     * 数据
     */
    private byte[] data;

    public MsgBody() {
    }

    public MsgBody(int seq, byte cmd, byte[] data) {
        this(seq, 0, cmd, data);
    }

    public MsgBody(int seq, int ack, byte cmd, byte[] data) {
        this.seq = seq;
        this.ack = ack;
        this.cmd = cmd;
        this.data = data;
    }

    public static MsgBody from(byte[] body) {
        MsgBody msg = new MsgBody();
        BytesReader br = new BytesReader(body);
        msg.setSeq(br.readInt4());
        msg.setAck(br.readInt4());
        msg.setCmd(br.read());
        msg.setData(br.readLast());
        return msg;
    }

    public byte[] toBytes() {
        int start = 4 + 4 + 1;
        int length = this.data.length;
        byte[] res = new byte[start + length];
        System.arraycopy(ByteUtil.intTo4Byte(this.seq), 0, res, 0, 4);
        System.arraycopy(ByteUtil.intTo4Byte(this.ack), 0, res, 4, 4);
        res[8] = this.cmd;
        System.arraycopy(this.data, 0, res, start, length);
        return res;
    }

    @Override
    public String toString() {
        return "MsgBody{" +
                "seq=" + seq +
                ", ack=" + ack +
                ", cmd=" + cmd +
                ", data=" + ByteUtil.toHex(data) +
                '}';
    }

    public int getSeq() {
        return seq;
    }

    public void setSeq(int seq) {
        this.seq = seq;
    }

    public int getAck() {
        return ack;
    }

    public void setAck(int ack) {
        this.ack = ack;
    }

    public byte getCmd() {
        return cmd;
    }

    public void setCmd(byte cmd) {
        this.cmd = cmd;
    }

    public byte[] getData() {
        return data;
    }

    public void setData(byte[] data) {
        this.data = data;
    }
}
